/*
 *	This program demonstrates a well-known dining philosophers problem.
 *	It uses spinlocks for syncrhonization.
 *
 *	Features demonstrated:
 * 		- Task switching
 * 		- Spinlock operations (creation, waiting and signalling)
 *	
 */

#include <stdio.h>

#include <avos/pt.h>

#include "hw.h"

pt_spin_t chopstick1, chopstick2;

void dining_philosopher(pt_t *pt, int philosopher)
{
	pt_start(pt);
	
	while (1) {
		printf("Philosopher %d is waiting for a pair of chopsticks\n", philosopher);
		pt_spin_lock(pt, &chopstick1);
		pt_spin_lock(pt, &chopstick2);

		printf("Philosopher %d picks up the chopsticks and is eating now.\n", philosopher);
		pt_sleep(pt, 2);

		printf("Philosopher %d puts the chopsticks back to the table\n", philosopher);

		pt_spin_unlock(pt, &chopstick1);
		pt_spin_unlock(pt, &chopstick2);
	}

	pt_end(pt);
}

int main(int argc, char *argv[])
{
	pt_t pt1, pt2, pt3;

	pt_init(&pt1);
	pt_init(&pt2);
	pt_init(&pt3);

	pt_spin_init(&chopstick1);
	pt_spin_init(&chopstick2);

	hw_init_timer();

	while (1) {
		(void) pt_schedule(&pt1, dining_philosopher(&pt1, 1));
		(void) pt_schedule(&pt2, dining_philosopher(&pt2, 2));
		(void) pt_schedule(&pt3, dining_philosopher(&pt3, 3));
	}
	return 0;
}
